class Importacion < ActiveRecord::Base
  attr_accessor :importados, :agregados, :descartados, :errores
  validates_presence_of :nombre
  has_many :movimientos, :dependent => :destroy
  has_many :marcaciones, :dependent => :destroy
  belongs_to :modelo
  def self.importar(modelo, archivo)
    nueva = Importacion.new
    begin
      nueva.importados = []
      filtros=filtros?(modelo.columnas)

      file=archivo.open
      if modelo.fila_inicio.to_i == 0
        modelo.fila_inicio = 1
      end
      header=modelo.encabezados
      if header
        while file.gets do
          if file.lineno==modelo.fila_inicio.to_i
            header=$_
            break
          end
        end
      end
      #Recorrer CSV ,:quote_char => "'"
      file=FasterCSV.parse(file,:col_sep => modelo.separador.strip, :headers => header, :encoding=>'U') do |row|
        error=nil
        unless filtros.empty?
          if !valida?(row,filtros)
            next
          end
        end
        fila = Hash.new

        #Recorrer columnas del modelo
        modelo.columnas.each do |col|
          if col.destino.empty?# col.origen se utiliza para solo filtro
            next
          end
          columna = (col.origen.to_i == 0 ? col.origen : col.origen.to_i-1)#Para saber si la columna origen es accedida por su nombre o por su indice
          if col.tipo_dato==2 #FechaHora
            begin
              row[columna]=DateTime.strptime(row[columna],modelo.formato_fecha).to_s
            rescue
              logger.info"Formato de fecha/hora incorrecto => #{row[columna]}"
            end
          elsif col.tipo_dato==1
            row[columna]=row[columna].gsub('.','') if row[columna]
          end

          if col.de_archivo?
            columna = (col.origen.to_i == 0 ? col.origen : col.origen.to_i-1)
            if col.use_proxy?
              #logger.info "columna: #{columna.pretty_inspect} col: #{col.pretty_inspect} row: #{row.pretty_inspect}"
              fila[col.destino.to_sym] = id_from_proxy(col.proxy, row[columna])
            else
              fila[col.destino.to_sym] = row[columna]
            end
            #TODO modificar metodo de calculo
            #TODO Tener en cuenta que #eval()
            # - utiliza el punto como separador decimal y no utiliza separador de millar
            # - Si el valor utiliza como separadores de millar el punto,  sustituirlos por ''
            # - Si el valor posee coma como separador decimal,  sustituirlos por '.'
          elsif col.calculada?
            begin
              fila[col.destino.to_sym]=eval(col.origen).is_a?(Class) ? "" : eval(col.origen)
            rescue SyntaxError,NameError
              columns=col.origen.split(/[(,),+,*,\/,-,=]/).delete_if{|x| x.to_f !=0 or x==""}
              columns.uniq!
              expresion=col.origen.clone
              columns.each do |c|
                if row.headers.include?(c)
                  if col.tipo_dato==0
                    row[c] = row[c].nil? ? "''" : "'"+row[c].to_s+"'"
                  else
                    row[c] = row[c].nil? ? "0" : row[c].to_s
                  end
                  expresion=expresion.gsub!(c,row[c].gsub('.',''))
                end
              end
              begin
                fila[col.destino.to_sym]=eval(expresion)
              rescue SyntaxError,StandardError,NameError =>er
                error=er
              end
            end
          else #Usar directamente el texto de la columna origen
            fila[col.destino.to_sym] = col.origen
          end
        end #each col
        
        unless error
          nueva.importados << fila
        else
          logger.info "ERROR => #{error}"
          break
        end

      end #each row
    rescue FasterCSV::MalformedCSVError => error
      logger.info('Error de CSV: '+error)
    rescue NoMethodError => error
      logger.info('Error de Metodo: '+error)
    end
    #Guarda en DB
      
    nueva.nombre = modelo.nombre
    nueva.modelo = modelo
    nueva.save
    nueva.agregados = []
    nueva.descartados = []


    unless (nueva.importados.nil?)
      linkear = modelo.modelo.constantize.new.methods.include?('importacion')
      nueva.importados.each_with_index  do |row,i|

        row=row.delete_if {|key, value| key == :filtros }
        mov = modelo.modelo.constantize.new(row)
        mov.importacion = nueva if linkear

        if mov.save
          nueva.agregados << mov
        else
          mov.errors.add_to_base("Fila del Error: #{modelo.fila_inicio+i}")
          nueva.descartados << mov
        end
      end
    end
    nueva
  end

  private

  def self.id_from_proxy(proxy, value)
    class_name,field_name = proxy.split(".")
    record = class_name.constantize.find(:first, :conditions => ["#{field_name}=?", value.strip])
    record.nil? ? "" : record.id
  end

  def self.filtros?(columnas)
    filtros={}
    columnas.each do |col|
      if filtros.empty? or filtros[:tipo]=='excluir'
        unless col.excluir.nil? || col.excluir.empty?
          filtros[:tipo]='excluir'
          filtros[col.origen.to_sym]=col.excluir
          next
        end
      end
      if filtros.empty? or filtros[:tipo]=='incluir'
        unless col.incluir.nil? || col.incluir.empty?
          filtros[:tipo]='incluir'
          filtros[col.origen.to_sym]=col.incluir
        end
      end
    end
    filtros
  end

  def self.valida?(fila,filtros)
    if filtros[:tipo]=='excluir'
      valida=true
    else
      valida=false
    end

    filtros.each do |col,filtro|

      if filtro.split(';').include?(fila[col.to_s])
        valida=!valida
        break
      end
    end
    return valida
  end

end
